home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / MDISTRM.PAK / MDISTRM.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  7.1 KB  |  287 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1993, 1995 by Borland International, All Rights Reserved
  4. //
  5. // This example shows a persistent desktop using the MDI metaphor.  It is
  6. // identical to the owlapi\mdi example, but with streaming code added to
  7. // implement persistence for the frame, parent (client) window, and children.
  8. //
  9. //----------------------------------------------------------------------------
  10. #include <owl/pch.h>
  11. #include <owl/applicat.h>
  12. #include <owl/mdi.h>
  13. #include <owl/mdichild.h>
  14. #include <stdio.h>
  15. #include "mdistrm.h"
  16.  
  17. const char DskFile[] = "MDISTRM.SAV";
  18. const char AppName[] = "MDI Object Streaming Example";
  19.  
  20. //----------------------------------------------------------------------------
  21.  
  22. //
  23. // Here's our client, it's fully streamable.
  24. //
  25. class TMyMDIClient : public TMDIClient {
  26.   public:
  27.     TMyMDIClient() : TMDIClient() {ChildNum = 0;}
  28.   
  29.     TMDIChild*  InitChild();
  30.     bool        CanClose();     //virtual from TWindow
  31.  
  32.   private:
  33.     uint16      ChildNum;
  34.     
  35.   DECLARE_STREAMABLE(, TMyMDIClient, 1);
  36. };
  37.  
  38. IMPLEMENT_CASTABLE1(TMyMDIClient, TMDIClient);
  39. IMPLEMENT_STREAMABLE1(TMyMDIClient, TMDIClient);
  40.  
  41. //
  42. // Our application object is also fully streamable and
  43. // we use it to stream out its client (which contains the
  44. // MDI child windows) to achieve a persistent desktop.
  45. //
  46. class TMDIApp : public TApplication {
  47.   public:
  48.     TMDIApp() : TApplication(AppName) {}
  49.     void InitMainWindow();
  50.     void InitInstance();
  51.     void CmSaveState();
  52.     void CmRestoreState();
  53.  
  54.   private:
  55.     TMyMDIClient* Client;
  56.  
  57.   DECLARE_RESPONSE_TABLE(TMDIApp);
  58.   DECLARE_STREAMABLE(, TMDIApp, 1);
  59. };
  60.  
  61. DEFINE_RESPONSE_TABLE1(TMDIApp, TApplication)
  62.   EV_COMMAND(CM_SAVESTATE, CmSaveState),
  63.   EV_COMMAND(CM_RESTORESTATE, CmRestoreState),
  64. END_RESPONSE_TABLE;
  65.  
  66. IMPLEMENT_CASTABLE1(TMDIApp, TApplication);
  67. IMPLEMENT_STREAMABLE1(TMDIApp, TApplication);
  68.  
  69.  
  70. //----------------------------------------------------------------------------
  71.  
  72. //
  73. //
  74. //
  75. TMDIChild*
  76. TMyMDIClient::InitChild()
  77. {
  78.   char childName[15];
  79.  
  80.   // Create a unique (numbered) caption for our MDI child
  81.   //
  82.   sprintf(childName, "MDI Child %d", ChildNum++);
  83.  
  84.   // and then create that child.
  85.   //
  86.   return new TMDIChild(*this, childName);
  87. }
  88.  
  89. //
  90. //
  91. //
  92. bool
  93. TMyMDIClient::CanClose()
  94. {
  95.   // Save our persistent desktop, before closing down the client.
  96.   // We have to (safely and dynamically) cast to our application
  97.   // object type so that we can call our save state routine.
  98.   //
  99.   TMDIApp *app = TYPESAFE_DOWNCAST(GetApplication(),TMDIApp);
  100.   if (app)
  101.     app->CmSaveState();
  102.  
  103.   return TMDIClient::CanClose();
  104. }
  105.  
  106. //
  107. // Writes the TMyMDIClient instance to the passed opstream.
  108. //
  109. void
  110. TMyMDIClient::Streamer::Write(opstream& os) const
  111. {
  112.   WriteBaseObject((TMDIClient*)GetObject(), os);
  113.   
  114.   // Write out the member data for our MDI Client.
  115.   os << GetObject()->ChildNum;
  116. }
  117.  
  118. //
  119. // Reads an instance of TMyMDIClient from the passed ipstream.
  120. //
  121. void *
  122. TMyMDIClient::Streamer::Read(ipstream& is, uint32 /*version*/) const
  123. {
  124.   ReadBaseObject((TMDIClient*)GetObject(), is);
  125.  
  126.   // Read in the member data for our MDI Client.
  127.   is >> GetObject()->ChildNum;
  128.  
  129.   return GetObject();
  130. }
  131.  
  132.  
  133. //----------------------------------------------------------------------------
  134.  
  135. //
  136. // Construct the TMDIApp's MainWindow (frame) object and save
  137. // a pointer to its client window in the Client data member.
  138. // Restore the desktop if we've got one already streamed.
  139. //
  140. void
  141. TMDIApp::InitMainWindow()
  142. {
  143.   // Create MDI frame window, load its menu, and create its client.
  144.   //
  145.   MainWindow = new TMDIFrame(GetName(), "MDIMenu", *(Client=new TMyMDIClient));
  146. }
  147.  
  148. //
  149. //
  150. //
  151. void
  152. TMDIApp::InitInstance()
  153. {
  154.   TApplication::InitInstance();
  155.  
  156.   // Restore our persistent desktop, if there's a stream that already exists.
  157.   //
  158.   ifpstream is(DskFile);
  159.   if (!is.bad())
  160.   {
  161.     is.close();
  162.     CmRestoreState();
  163.   }
  164. }
  165.  
  166. //
  167. // Save the the position and contents of the windows to the "desktop" file.
  168. //
  169. void
  170. TMDIApp::CmSaveState()
  171. {
  172.   ofpstream os(DskFile);
  173.  
  174.   // Stream out 'this' object (our MDI application and children).
  175.   //
  176.   os << *this;
  177.  
  178.   os.close();
  179.  
  180.   if (os.bad()) {
  181.     unlink(DskFile);
  182.     MainWindow->MessageBox("Unable to write desktop file.", "Disk error",
  183.                            MB_OK | MB_ICONEXCLAMATION);
  184.   }
  185. }
  186.  
  187. //
  188. // Read windows' positions and contents from the "desktop" file.
  189. //
  190. void
  191. TMDIApp::CmRestoreState()
  192. {
  193.   char* errorMsg = 0;
  194.  
  195.   ifpstream is(DskFile);
  196.   if (is.bad())
  197.     errorMsg = "Unable to open desktop file.";
  198.  
  199.   else {
  200.     // Close any MDI children we may have.
  201.     //
  202.     Client->CloseChildren();
  203.     try {
  204.       // Stream into 'this' object our (new) MDI application and children.
  205.       //
  206.       is >> *this;
  207.       if (is.bad())
  208.         errorMsg = "Error reading desktop file.";
  209.     }
  210.     catch (xalloc) {
  211.       if (Client->HWindow)
  212.         Client->CloseChildren();
  213.       errorMsg = "Not enough memory to open file.";
  214.     }
  215.     is.close();
  216.   }
  217.   if (errorMsg)
  218.     MainWindow->MessageBox(errorMsg, "Error", MB_OK | MB_ICONEXCLAMATION);
  219. }
  220.  
  221. //
  222. //
  223. //
  224. void 
  225. TMDIApp::Streamer::Write(opstream& os) const
  226. {
  227.   // Stream out our app's mainwindow size/coordinates and our client
  228.   // window (the client will stream any child windows it may contain).
  229.   //
  230.   WriteBaseObject((TApplication*)GetObject(), os);
  231.   os << GetObject()->MainWindow->Attr.X;
  232.   os << GetObject()->MainWindow->Attr.Y;
  233.   os << GetObject()->MainWindow->Attr.W;
  234.   os << GetObject()->MainWindow->Attr.H;
  235.  
  236.   os << *( GetObject()->Client );
  237.   os << GetObject()->Client->GetActiveMDIChild();
  238. }
  239.  
  240. //
  241. //
  242. //
  243. void*
  244. TMDIApp::Streamer::Read(ipstream& is, uint32 /*version*/ ) const
  245. {
  246.   // Stream in our app's mainwindow frame coordinates, updating its frame
  247.   // size, and stream in its client window.
  248.   //
  249.   ReadBaseObject((TApplication*)GetObject(), is);
  250.   is >> GetObject()->MainWindow->Attr.X;
  251.   is >> GetObject()->MainWindow->Attr.Y;
  252.   is >> GetObject()->MainWindow->Attr.W;
  253.   is >> GetObject()->MainWindow->Attr.H;
  254.  
  255.   is >> *( GetObject()->Client );
  256.   TMDIChild* active;
  257.   is >> active;
  258.  
  259.   // If our mainwindow already exists (i.e., we're restoring from the menu)
  260.   // then make sure it's redrawn correctly, with the 'new' extent attributes
  261.   // (what they were when they were last streamed to file).
  262.   //
  263.   if (GetObject()->MainWindow->HWindow)
  264.     GetObject()->MainWindow->MoveWindow(GetObject()->MainWindow->Attr.X,
  265.                                         GetObject()->MainWindow->Attr.Y,
  266.                                         GetObject()->MainWindow->Attr.W,
  267.                                         GetObject()->MainWindow->Attr.H,
  268.                                         true);
  269.  
  270.   // Finally, create the interface objects for our children,
  271.   // restoring the active window.
  272.   //
  273.   GetObject()->Client->CreateChildren();
  274.   if (active)
  275.     GetObject()->Client->HandleMessage(WM_MDIACTIVATE,(uint)active->GetHandle());
  276.   return GetObject();
  277. }
  278.  
  279. //
  280. //
  281. //
  282. int
  283. OwlMain(int /*argc*/, char* /*argv*/ [])
  284. {
  285.   return TMDIApp().Run();
  286. }
  287.